import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { CheckboxModule, GroupModule } from '@iux/live';

@Component({
  template: `
    <label
      lv-checkbox
      [(ngModel)]="open"
      [lvControl]="lvControl"
      [lvViewType]="lvViewType"
      [lvButtonSize]="lvButtonSize"
      [lvDisabled]="lvDisabled"
      [lvIndeterminate]="lvIndeterminate"
    >
      Checkbox1
    </label>
    <lv-checkbox-group [(ngModel)]="selected">
      <lv-group [lvGutter]="'48px'">
        <lv-checkbox-all>Check All</lv-checkbox-all>
        <lv-checkbox [lvValue]="'item001'">Item 001</lv-checkbox>
        <lv-checkbox [lvValue]="'item002'">Item 002</lv-checkbox>
        <lv-checkbox [lvValue]="'item003'">Item 003</lv-checkbox>
        <lv-checkbox [lvValue]="'item004'">Item 004</lv-checkbox>
        <lv-checkbox [lvValue]="'item005'">Item 005</lv-checkbox>
      </lv-group>
    </lv-checkbox-group>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
class TestCheckboxComponent {
  open = true;
  selected: string[] = ['item001', 'item002', 'item003', 'item004', 'item005'];
  @Input() lvIndeterminate = true; // 是否为半选
  @Input() lvDisabled = false;
  @Input() lvViewType: 'default' | 'button' | 'link' | 'custom' = 'default';
  @Input() lvButtonSize: 'default' | 'small' = 'default';
  @Input() lvControl: boolean = false;
}

describe('CheckboxComponent', () => {
  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      declarations: [TestCheckboxComponent],
      imports: [CheckboxModule, FormsModule, GroupModule, NoopAnimationsModule],
      teardown: { destroyAfterEach: false },
    }).compileComponents();
  }));

  describe('render', () => {
    let component: TestCheckboxComponent;
    let fixture: ComponentFixture<TestCheckboxComponent>;
    const renderComp = fakeAsync(para => {
      for (const [key, value] of Object.entries(para)) {
        component[key] = value;
      }
      fixture.detectChanges();
      tick(500);
      fixture.detectChanges();
      expect(fixture).toMatchSnapshot();
    });

    beforeEach(() => {
      fixture = TestBed.createComponent(TestCheckboxComponent);
      component = fixture.componentInstance;
    });

    it('with lvIndeterminate', () => {
      renderComp({ lvIndeterminate: false });
    });

    it('with lvDisabled', () => {
      renderComp({ lvDisabled: true });
    });

    it('with lvViewType is button', () => {
      renderComp({ lvViewType: 'button' });
    });

    it('with lvViewType is link', () => {
      renderComp({ lvViewType: 'link' });
    });

    it('with lvButtionSize', () => {
      renderComp({ lvViewType: 'small' });
    });

    it('with lvControl', () => {
      renderComp({ lvControl: true });
    });
  });

  describe('work', () => {
    let component: TestCheckboxComponent;
    let fixture: ComponentFixture<TestCheckboxComponent>;
    const checkedClass = 'lv-checkbase-checked';

    beforeEach(() => {
      fixture = TestBed.createComponent(TestCheckboxComponent);
      component = fixture.componentInstance;
    });

    // 正常选择切换
    it('should work when click', fakeAsync(() => {
      component.lvControl = false;
      component.lvIndeterminate = false;
      fixture.detectChanges();

      const checkedItem = fixture.nativeElement.querySelector(`label`);

      checkedItem.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(500);

      expect(checkedItem.className).toContain(`${checkedClass}`);
    }));

    // 状态外部控制测试
    it('should work when control', fakeAsync(() => {
      component.lvControl = true;
      component.lvIndeterminate = false;
      component.open = true;
      fixture.detectChanges();
      tick(500);
      fixture.detectChanges();

      const checkedItem = fixture.nativeElement.querySelector(`label`);
      expect(checkedItem.className).toContain(`${checkedClass}`);

      checkedItem.dispatchEvent(new Event('click'));
      component.open = false;

      fixture.detectChanges();
      tick(500);
      fixture.detectChanges();
      expect(checkedItem.className).not.toContain(`${checkedClass}`);
    }));

    // 取消全选
    it('should work with check all', fakeAsync(() => {
      fixture.detectChanges();
      tick(500);
      fixture.detectChanges();

      const checkboxAll = fixture.nativeElement.querySelector('lv-checkbox-all');

      checkboxAll.dispatchEvent(new Event('click'));

      fixture.detectChanges();
      tick(500);
      fixture.detectChanges();

      expect(checkboxAll.className).not.toContain(`${checkedClass}`);
      const checkedItem = fixture.nativeElement.querySelector('lv-checkbox');
      expect(checkedItem.className).not.toContain(`${checkedClass}`);
    }));
  });
});
